package services

import (
	"fmt"
	"github.com/gorilla/websocket"
	"sen-golang-study/go_game_study/hero_story_go_server/common"
	"sen-golang-study/go_game_study/hero_story_go_server/common/log"
	"sen-golang-study/go_game_study/hero_story_go_server/gateway_server/internal/domain/entity"
	"sen-golang-study/go_game_study/hero_story_go_server/gateway_server/internal/domain/repository"
	"sen-golang-study/go_game_study/hero_story_go_server/gateway_server/internal/domain/service"
)

type GatewayService struct {
	sessionService *service.SessionService
	serverConnRepo *repository.ServerConnRepository
	serverSelector *entity.ServerSelector
}

func NewGatewayService(
	sessionRepo *repository.SessionRepository,
	serverConnRepo *repository.ServerConnRepository,
	messageRouter *entity.MessageRouter,
	serverSelector *entity.ServerSelector,
) *GatewayService {
	sessionService := service.NewSessionService(sessionRepo, serverConnRepo, messageRouter, serverSelector)

	return &GatewayService{
		sessionService: sessionService,
		serverConnRepo: serverConnRepo,
		serverSelector: serverSelector,
	}
}

func (gs *GatewayService) HandleWebSocketConnection(conn *websocket.Conn) {
	gs.sessionService.HandleNewConnection(conn)
}

func (gs *GatewayService) ConnectToGameServer(serverInfo *common.GameServerInfo) {
	if serverInfo.ServerId == 0 || len(serverInfo.ServiceAddr) == 0 {
		log.Error("[ConnectToGameServer] serverID or serverAddr is null")
		return
	}

	// 检查连接是否已存在
	_, err := gs.serverConnRepo.GetConnection(serverInfo.ServerId)
	if err == nil {
		// 连接已存在，只更新服务器信息
		gs.serverSelector.UpdateServer(serverInfo)
		return
	}

	// 建立新连接
	newGameServerConn, _, err := websocket.DefaultDialer.Dial(fmt.Sprintf("ws://%s/websocket", serverInfo.ServiceAddr), nil)
	if err != nil {
		log.Error("连接游戏服务失败 %+v", err)
		return
	}

	log.Info("成功连接到游戏服务器,serverID=%d,serverAddr=%s,responsibilities=%v",
		serverInfo.ServerId, serverInfo.ServiceAddr, serverInfo.Responsibilities)

	// 保存连接
	err = gs.serverConnRepo.SaveConnection(serverInfo.ServerId, newGameServerConn)
	if err != nil {
		log.Error("保存游戏服务连接失败 %+v", err)
		return
	}
	// 更新服务器信息
	gs.serverSelector.UpdateServer(serverInfo)
	// 启动消息循环
	gs.serverConnRepo.StartMessageLoop(serverInfo.ServerId)
}

func (gs *GatewayService) RemoveGameServer(serverID uint32) {
	err := gs.serverConnRepo.RemoveConnection(serverID)
	if err != nil {
		log.Error("删除游戏服务连接失败 %+v", err)
		return
	}
	gs.serverSelector.RemoveServer(serverID)
	log.Info("移除游戏服务器连接，serverID=%d", serverID)
}
